home *** CD-ROM | disk | FTP | other *** search
/ Power DOS 1996 July / Power DOS - July 1996.iso / sound / c_labs / devinfo / mpu401.exe / MIDIUTIL.C < prev    next >
C/C++ Source or Header  |  1996-04-18  |  11KB  |  344 lines

  1. /* -------------------------------------------------------------------------- */
  2. /* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      */
  3. /* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE        */
  4. /* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR      */
  5. /* PURPOSE.                                                                   */
  6. /*                                                                            */
  7. /* You have a royalty-free right to use, modify, reproduce and                */
  8. /* distribute the Sample Files (and/or any modified version) in               */
  9. /* any way you find useful, provided that you agree that                      */
  10. /* Creative has no warranty obligations or liability for any Sample Files.    */
  11. /*----------------------------------------------------------------------------*/
  12.  
  13.  
  14. /* ---------------------------------------------------------------------------
  15.   Program:  Sound Blaster 16 MIDI Utilities
  16.   Filename: MIDIUTIL.C
  17.   Author:   Scott E. Sindorf
  18.   Language: Borland C
  19.   Date:     30 Jun 93
  20.   
  21.   Copyright (c) 1993-1996 Creative Labs, Inc.
  22. -----------------------------------------------------------------------------*/
  23.  
  24. #include <conio.h>
  25. #include "midiutil.h"
  26. #include "sbcutils.h"
  27.  
  28. extern BLASTREC blastInfo;
  29.  
  30. int MIDIType = MPU401;                    // MIDI type to use flag
  31.  
  32. /************************************************************************
  33.  * WRITE_MPU401_CMD: sends a command to the MPU401 port.
  34.  *
  35.  * Input: command - command byte
  36.  *
  37.  * Output: none
  38.  ************************************************************************/
  39. void Write_MPU401_Cmd(unsigned char command)
  40. {
  41.   // check write status
  42.   while((inp(blastInfo.midiPort + 1) & MPU401_OK2WR));
  43.  
  44.   outp(blastInfo.midiPort + 1, command);
  45. }
  46.  
  47. /************************************************************************
  48.  * WRITE_MPU401_DATA: sends a data byte to the MPU401 port.
  49.  *
  50.  * Input: data - data byte
  51.  *
  52.  * Output: none
  53.  ************************************************************************/
  54. void Write_MPU401_Data(unsigned char data)
  55. {
  56.   // check write status
  57.   while((inp(blastInfo.midiPort + 1) & MPU401_OK2WR));
  58.  
  59.   outp(blastInfo.midiPort, data);
  60. }
  61.  
  62. /************************************************************************
  63.  * WRITE_SBMIDI_DATA: sends a byte to the Sound Blaster MIDI port.
  64.  *
  65.  * Input: data - data byte
  66.  *
  67.  * Output: none
  68.  ************************************************************************/
  69. void Write_SBMIDI_Data(unsigned char data)
  70. {
  71.   // wait for write buffer ready
  72.   while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
  73.   // send MIDI write command
  74.   outp(blastInfo.baseAddr + DSP_WR, MIDI_OUT_P);
  75.  
  76.   // wait for write buffer ready
  77.   while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
  78.   // send MIDI data byte
  79.   outp(blastInfo.baseAddr + DSP_WR, data);
  80. }
  81.  
  82. /************************************************************************
  83.  * READ_MPU401_DATA: reads a byte from the MPU401 port.
  84.  *
  85.  * Input: none
  86.  *
  87.  * Output: data byte
  88.  ************************************************************************/
  89. unsigned char Read_MPU401_Data(void)
  90. {
  91.   // check read status
  92.   while((inp(blastInfo.midiPort + 1) & MPU401_OK2RD));
  93.  
  94.   return(inp(blastInfo.midiPort));
  95. }
  96.  
  97. /************************************************************************
  98.  * READ_SBMIDI_DATA: reads a byte from the Sound Blaster MIDI port.
  99.  *
  100.  * Input: none
  101.  *
  102.  * Output: data - data byte
  103.  ************************************************************************/
  104. unsigned char Read_SBMIDI_Data(void)
  105. {
  106.   unsigned char data;
  107.  
  108.   // wait for write buffer ready
  109.   while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
  110.   // send MIDI read command
  111.   outp(blastInfo.baseAddr + DSP_WR, MIDI_IN_P);
  112.   // wait for read buffer ready
  113.   while(!(inp(blastInfo.baseAddr + DSP_RD_ST) & MSB));
  114.   // read MIDI data byte
  115.   data = inp(blastInfo.baseAddr + DSP_RD);
  116.   // wait for write buffer ready
  117.   while(inp(blastInfo.baseAddr + DSP_WR_ST) & MSB);
  118.   // stop MIDI read
  119.   outp(blastInfo.baseAddr + DSP_WR, MIDI_IN_P);
  120.   return(data);
  121. }
  122.  
  123. /************************************************************************
  124.  * SEND_MIDI_MESSAGE: Sends a MIDI message to port
  125.  *
  126.  * Input: message - MIDI message to send
  127.  *        size - length of message
  128.  *
  129.  * Output: none
  130.  ************************************************************************/
  131. void Send_MIDI_Message(char far *message, int size)
  132. {
  133.   int i;
  134.  
  135.   if(MIDIType == MPU401)
  136.     for(i = 0; i < size; i++)
  137.       Write_MPU401_Data(message[i]);
  138.   else
  139.     for(i = 0; i < size; i++)
  140.       Write_SBMIDI_Data(message[i]);
  141. }
  142.  
  143. /************************************************************************
  144.  * SET_MIDI_VOL: Sets the global volume on the requested channel
  145.  *
  146.  * Input: channel - set volume on this channel (1 to 16)
  147.  *        volume - set channel to this volume (0 to 127)
  148.  *
  149.  * Output: none
  150.  *
  151.  * note: if inputs are out of range then no action occurs
  152.  ************************************************************************/
  153. void Set_MIDI_Vol(char channel, char volume)
  154. {
  155.   char message[3];
  156.  
  157.   if((channel <= 16) && (channel > 0))
  158.     if(volume >= 0)
  159.     {
  160.       message[0] = 0xb0 + channel - 1;    // set channel
  161.       message[1] = 7;                     // set global volume command
  162.       message[2] = volume;                // set volume level
  163.       Send_MIDI_Message(message, 3);
  164.     }
  165. }
  166.  
  167. /************************************************************************
  168.  * SET_MIDI_NOTES_OFF: Turns off all notes on the given channel
  169.  *
  170.  * Input: channel - turns off all notes on this channel (1 to 16)
  171.  *
  172.  * Output: none
  173.  *
  174.  * note: if channel is out of range then no action occurs
  175.  ************************************************************************/
  176. void Set_MIDI_Notes_Off(char channel)
  177. {
  178.   char message[3];
  179.  
  180.   if((channel <= 16) && (channel > 0))
  181.   {
  182.     message[0] = 0xb0 + channel - 1;      // set channel
  183.     message[1] = 0x7b;                    // clear all notes command
  184.     message[2] = 0;
  185.     Send_MIDI_Message(message, 3);
  186.   }
  187. }
  188.  
  189. /************************************************************************
  190.  * SET_MIDI_PITCH_BEND: Sets pitch bend (0 = OFF).
  191.  *
  192.  * Input: channel - sets pitch bend on this channel (1 to 16)
  193.  *        bend - pitch bend value (-8192 to 8191)
  194.  *
  195.  * Output: none
  196.  *
  197.  * note: if inputs are out of range then no action occurs
  198.  ************************************************************************/
  199. void Set_MIDI_Pitch_Bend(char channel, int range)
  200. {
  201.   char message[3];
  202.  
  203.   if((channel <= 16) && (channel > 0))
  204.     if((range >= -8192) && (range < 8192))
  205.     {
  206.       range += 8192;
  207.       message[0] = 0xe0 + channel - 1;    // set channel
  208.       message[1] = range >> 7;            // set pitch bend (MSB)
  209.       message[2] = range & 0x7f;          // set pitch bend (LSB)
  210.       Send_MIDI_Message(message, 3);
  211.     }
  212. }
  213.  
  214. /************************************************************************
  215.  * RESET_MPU401: resets the MPU401 port.
  216.  *
  217.  * Input: none
  218.  *
  219.  * Output: result - (0 = OK, -1 = ERROR)
  220.  *
  221.  * note: Error will occur if UART mode is not turned off first.
  222.  ************************************************************************/
  223. int Reset_MPU401(void)
  224. {
  225.   int i = 100;
  226.  
  227.   Write_MPU401_Cmd(MPU401_RESET);         // send reset command
  228.   while((i > 0) && (Read_MPU401_Data() != MPU401_CMDOK))
  229.     i--;                                  // offer timeout instead of lockup
  230.  
  231.   if(i == 0)
  232.     return(ERROR);
  233.   else
  234.     return(OK);
  235. }
  236.  
  237. /************************************************************************
  238.  * SET_UART_MODE: puts the MPU401 port in UART mode.
  239.  *
  240.  * Input: state - ON or OFF (Reset will return error if UART mode is on
  241.  *                when reset occurs)
  242.  *
  243.  * Output: result - (0 = OK, -1 = ERROR)
  244.  ************************************************************************/
  245. int Set_UART_Mode(int state)
  246. {
  247.   int i = 100;
  248.  
  249.   if(state == ON)
  250.   {
  251.     Write_MPU401_Cmd(MPU401_UART);        // turn on UART mode
  252.     while((i > 0) && (Read_MPU401_Data() != MPU401_CMDOK))
  253.       i--;                                // offer timeout instead of lockup
  254.   }
  255.   else
  256.     Write_MPU401_Cmd(MPU401_RESET);       // turn off UART mode
  257.  
  258.   if(i == 0)
  259.     return(ERROR);
  260.   else
  261.     return(OK);
  262. }
  263.  
  264. /************************************************************************
  265.  * DETECT_MIDI: Detects the presence of the MPU-401 port or the SBMIDI
  266.  *              port.
  267.  *
  268.  * Input: none
  269.  *
  270.  * Output: result - (0 = OK if found, -1 = ERROR if not found)
  271.  ************************************************************************/
  272. int Detect_MIDI(void)
  273. {
  274.   unsigned char status;
  275.   int result = ERROR;
  276.  
  277.   if(MIDIType == MPU401)
  278.   {
  279.     // check write status
  280.     status = inp(blastInfo.midiPort + 1);
  281.  
  282.     if(!(status & MPU401_OK2WR))
  283.     {
  284.       Set_UART_Mode(OFF);                 // just in case it was left on
  285.       result = Reset_MPU401();            // does reset work?
  286.     }
  287.   }
  288.   else
  289.     result = DSPReset();                  // reset the DSP
  290.  
  291.   return(result);
  292. }
  293.  
  294. /************************************************************************
  295.  * INIT_MIDI: Initializes the MIDI port.  If MPU-401 port then reset
  296.  *            the port and select UART mode.  For either MPU-401 or
  297.  *            SBMIDI ports set all master volumes to 100, turn off all
  298.  *            notes, and reset all pitch bends.
  299.  *
  300.  * Input: none
  301.  *
  302.  * Output: result - (0 = OK, -1 = ERROR)
  303.  ************************************************************************/
  304. int Init_MIDI(void)
  305. {
  306.   int i;
  307.  
  308.   if(MIDIType == MPU401)
  309.   {
  310.     if(Reset_MPU401() == ERROR)           // reset port
  311.       return(ERROR);
  312.  
  313.     if(Set_UART_Mode(ON) == ERROR)        // set UART mode
  314.       return(ERROR);
  315.   }
  316.  
  317.   for(i = 1; i <= 16; i++)
  318.   {
  319.     Set_MIDI_Vol(i, 100);                 // set channel volume
  320.     Set_MIDI_Notes_Off(i);                // turn off all notes
  321.     Set_MIDI_Pitch_Bend(i, 0);            // reset pitch bends
  322.   }
  323.   return(OK);
  324. }
  325.  
  326. /************************************************************************
  327.  * EXIT_MIDI: Terminates MIDI driver by turning off all notes (and
  328.  *            turning off UART mode if using MPU-401 port).
  329.  *
  330.  * Input: none
  331.  *
  332.  * Output: none
  333.  ************************************************************************/
  334. void Exit_MIDI(void)
  335. {
  336.   int i;
  337.  
  338.   for(i = 0; i < 16; i++)
  339.     Set_MIDI_Notes_Off(i);                // turn off all notes
  340.  
  341.   if(MIDIType == MPU401)
  342.     Set_UART_Mode(OFF);                   // exit UART mode
  343. }
  344.